import json
import os
import time
import uuid

from flask import session

from app.Models.Files import FileForBM
from app.Models.Model import BmFile
from app.Service.FileService import FileService
from app.Vendor.ApiException import illegalUserErr, fileSaveErr, fileDeleteErr
from app.Vendor.Utils import Utils
from app.env import TEMP_FILE_WEB_PATH, EXAMPLE_WEB_FOLDER


class PasserByService:
    def getProjectInfo(self):
        dataPath = session.get("webdata")
        labelPath = session.get("weblabel")
        coordinatePath = session.get("webcoordinate")
        dataShape = session.get("dataShape")
        labelShape = session.get("labelShape")
        coordinateShape = session.get("coordinateShape")
        fileDict = dict(dataPath=dataPath, labelPath=labelPath, coordinatePath=coordinatePath, dataShape=dataShape,
                        labelShape=labelShape, coordinateShape=coordinateShape)
        return fileDict

    def setProjectFile(self):
        session["data"] = "app/Uploads/example1/data.csv"
        session["label"] = "app/Uploads/example1/label.csv"
        session["coordinate"] = "app/Uploads/example1/coordinate.csv"
        session["webdata"] = EXAMPLE_WEB_FOLDER + "example1/data.csv"
        session["weblabel"] = EXAMPLE_WEB_FOLDER + "example1/label.csv"
        session["webcoordinate"] = EXAMPLE_WEB_FOLDER + "example1/coordinate.csv"
        session["dataShape"] = dict(FileShape1=50, FileShape2=157)
        session["labelShape"] = dict(FileShape1=50, FileShape2=2)
        session["coordinateShape"] = dict(FileShape1=157, FileShape2=1)

    def setProjectFile2(self):
        session["data"] = "app/Uploads/example2/data.csv"
        session["label"] = "app/Uploads/example2/label.csv"
        session["coordinate"] = "app/Uploads/example2/coordinate.csv"
        session["webdata"] = EXAMPLE_WEB_FOLDER + "example2/data.csv"
        session["weblabel"] = EXAMPLE_WEB_FOLDER + "example2/label.csv"
        session["webcoordinate"] = EXAMPLE_WEB_FOLDER + "example1/coordinate.csv"
        session["dataShape"] = dict(FileShape1=139, FileShape2=8600)
        session["labelShape"] = dict(FileShape1=139, FileShape2=2)
        session["coordinateShape"] = dict(FileShape1=8600, FileShape2=1)

    def getUserInfo(self):
        userId = session.get("userId")
        projectId = session.get("projectIdNow")
        if (userId is None or projectId is None):
            raise illegalUserErr()
        return userId, projectId

    def getState(self):
        userId = session.get("userId")
        projectId = session.get("projectIdNow")
        data = session.get("data")
        label = session.get("label")
        coordinate = session.get("coordinate")
        if (
                userId == None or projectId == None or projectId == None or data == None or label == None or coordinate == None):
            return False
        return True

    def setFileShapeInfo(self, dataShape, shape):
        session[dataShape] = shape

    def getProjectFileInfo(self):
        userId = session.get("userId")
        projectId = session.get("projectIdNow")
        data = session.get("data")
        label = session.get("label")
        coordinate = session.get("coordinate")
        return userId, projectId, data, label, coordinate

    def passerByLogin(self):
        if session.get("userId") == None:
            userId = str(time.time()).split('.')[0] + '_' + ''.join(str(uuid.uuid4()).split('-'))
            session["userId"] = userId
        projectList = session.get("projectList")
        if projectList == None:
            projectList = []
        if session.get("projectIdNow") == None:
            projectId = ''.join(str(uuid.uuid4()).split('-'))
            session["projectIdNow"] = projectId
            projectList.append(projectId)
        session["projectList"] = projectList
        datalist = json.dumps(projectList)
        userId = session["userId"]
        projectId = session["projectIdNow"]

        return userId, projectId, datalist

    def getWebPath(self, filename):
        userId, projectId = self.getUserInfo()
        path = TEMP_FILE_WEB_PATH + userId + '/' + projectId + '/' + filename
        return path

    def deletefile(self, filename, saveDir):
        try:
            filetype = filename.split('.')[0]
            webfileType = "web" + filetype
            fileShape = filetype + "Shape"
            session[filetype] = None
            session[webfileType] = None
            session[fileShape] = None
            if (os.path.isfile(saveDir + filename)):
                os.remove(saveDir + filename)
        except Exception:
            raise fileDeleteErr()

    def savefile(self, files, filetype, saveDir):
        filename = files.filename
        new_filename = filetype + '.' + filename.split('.')[1]
        webfileType = "web" + filetype
        session[filetype] = None
        session[webfileType] = None
        if (files and Utils.allowed_file(filename)):
            path = saveDir + new_filename
            webPath = self.getWebPath(new_filename)
            files.save(path)
            session[filetype] = path
            session[webfileType] = webPath
            projectId = session.get("projectIdNow")
            filters = {
                BmFile.project_id == projectId
            }
            userData = FileForBM().getOne(filters)
            if (userData == None):
                FileService().add(projectId)
            FileService().update(projectId, filetype, path)
            return path, webPath
        else:
            raise fileSaveErr()

    def examFileShape(self):
        infoDict = self.getProjectInfo()
        shape1 = infoDict["dataShape"]["FileShape1"]
        shape2 = infoDict["dataShape"]["FileShape2"]
        shape3 = infoDict["labelShape"]["FileShape1"]
        shape4 = infoDict["labelShape"]["FileShape2"]
        shape5 = infoDict["coordinateShape"]["FileShape1"]
        shape6 = infoDict["coordinateShape"]["FileShape2"]
        if (shape1 == shape3 and shape2 == shape5 and shape6 == 1):
            # shape1是样本个数，shape2是样本维度，shape4是标签的个数
            return shape1, shape2, shape4
        else:
            return False
